package com.sxdz.pay

import com.fasterxml.jackson.databind.ObjectMapper
import com.sxdz.constant.CommonConstant
import com.sxdz.constant.GlobalConstant
import com.sxdz.controller.handler.RequestRemoteHandler
import com.sxdz.pay.util.MD5
import com.sxdz.pay.util.SignUtils
import com.sxdz.pay.util.XmlUtils
import groovy.transform.CompileStatic
import groovy.transform.TypeChecked
import me.chanjar.weixin.mp.bean.WxMpTemplateMessage
import org.apache.http.client.methods.CloseableHttpResponse
import org.apache.http.client.methods.HttpPost
import org.apache.http.entity.StringEntity
import org.apache.http.impl.client.CloseableHttpClient
import org.apache.http.impl.client.HttpClients
import org.apache.http.util.EntityUtils
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.stereotype.Component

import java.text.SimpleDateFormat

/**
 * Created by lzw on 2016/8/16.
 * 移动支付接口
 */
@CompileStatic
@TypeChecked
@Component
class PayMentApi {
    private final static String version = "2.0";
    private final static String charset = "UTF-8";
    private final static String sign_type = "MD5";
    /**
     * 订单提交
     * @param outTradeNo
     * @param body
     * @param attach
     * @param totalFee
     * @param mchCreateIp
     * @param timeStart
     * @param timeExpire
     * @return
     */
    public static payInfo(String openId, String outTradeNo, String body, String attach, String totalFee, String
            timeStart, String timeExpire,String orderId,String openid) throws Exception {
        Logger logger = LoggerFactory.getLogger(PayMentApi.getClass())
        /**
         * （out_trade_no-- 、body--、attach--附加信息、total_fee--总金额、mch_create_ip--终端IP）必须存在
         * time_start--订单生成时间、time_expire--订单超时时间[格式都是yyyymmddhhmmss]
         */
        try {

            SortedMap<String, String> map = new TreeMap<String, String>()//写入集合的数据是有序的

            map.put("out_trade_no", outTradeNo)//商户订单号

            map.put("body", body)//商品描述
            map.put("attach", attach)//附加信息
            map.put("total_fee", totalFee)//总金额
            map.put("mch_create_ip", "127.0.0.1")//终端IP
            map.put("time_start", timeStart)//订单生成时间
            map.put("time_expire", timeExpire)//订单超时时间
            map.put("service", "pay.weixin.jspay");
            map.put("version", version);
            map.put("charset", charset);
            map.put("sign_type", sign_type);
            map.put("mch_id", GlobalConstant.getString("mch_id"));
            if(!"7551000001".equals(GlobalConstant.getString("mch_id"))){ //非测试商户ID
                map.put("sub_openid",openId)//用户openid
            }
            String callbackUrl=GlobalConstant.getString("callback_url");
            //callbackUrl+="?orderId="+orderId+"%26openId="+openid
            callbackUrl=callbackUrl.replaceAll("orderId1",orderId);
            callbackUrl=callbackUrl.replaceAll("openId2",openid);
            map.put("notify_url",GlobalConstant.getString("notify_url"));
            map.put("callback_url", callbackUrl);
            map.put("nonce_str", String.valueOf(new Date().getTime()));
            Map<String, String> params = SignUtils.paraFilter(map);
            StringBuilder buf = new StringBuilder((params.size() + 1) * 10);
            SignUtils.buildPayParams(buf, params, false);
            String preStr = buf.toString();
            String sign = MD5.sign(preStr, "&key=" + GlobalConstant.getString("key"), "utf-8");
            map.put("sign", sign);

            String reqUrl = GlobalConstant.getString("req_url");
            CloseableHttpResponse response = null;
            CloseableHttpClient client = null;
            String res = null;
            Map<String, String> resultMap = null;
            try {
                HttpPost httpPost = new HttpPost(reqUrl);
                StringEntity entityParams = new StringEntity(XmlUtils.parseXML(map), "utf-8");
                httpPost.setEntity(entityParams);
                httpPost.setHeader("Content-Type", "text/xml;charset=ISO-8859-1");
                client = HttpClients.createDefault();
                response = client.execute(httpPost);
                if (response != null && response.getEntity() != null) {
                    resultMap = XmlUtils.toMap(EntityUtils.toByteArray(response.getEntity()), "utf-8");
                    res = XmlUtils.toXml(resultMap);
                    if (!SignUtils.checkParam(resultMap, GlobalConstant.getString("key"))) {
                        res = "验证签名不通过";
                    } else {
                        if ("0".equals(resultMap.get("status")) && "0".equals(resultMap.get("result_code"))) {
                            res = "ok";
                        }
                    }
                } else {
                    res = "操作失败";
                }
            } catch (Exception e) {
                res = "系统异常";
                logger.error("================调用支付接口初始化出现异常===================", e)
            } finally {
                if (response != null) {
                    response.close();
                }
                if (client != null) {
                    client.close();
                }
            }
            Map<String, String> result = new HashMap<String, String>();
            if ("ok".equals(res)) {
                result = resultMap;
            } else {
                result.put("status", "500");
                result.put("msg", res);
            }

            ObjectMapper om = new ObjectMapper();
            om.setDateFormat(new SimpleDateFormat("yyyyMMddHH:mm:ss"));
            String json = om.writeValueAsString(resultMap)
            logger.info("===============支付初始化返回结果=============：" + json)
            return json;
        } catch (Exception ex) {
            [resCode: CommonConstant.ErrorMsg.E9001.value]
            logger.error("================调用支付接口初始化出现异常===================", ex)
        }
    }

    /**
     * 支付退款接口
     * @param outTradeNo
     * @param transactionId
     * @param outRefundNo
     * @param totalFee
     * @param refundFee
     */

    public
    static submitRefund(String openId, String outTradeNo, String transactionId, String outRefundNo, String totalFee, String refundFee, String refundChannel) throws Exception {

        Logger logger = LoggerFactory.getLogger(PayMentApi.getClass())
        logger.info("=============================支付退款接口进入=====================");
        SortedMap<String, String> map = new TreeMap<String, String>()
        map.put("out_trade_no", outTradeNo)//商户订单号
        map.put("transaction_id", transactionId)//威富通订单号
        map.put("out_refund_no", outRefundNo)//商户退单单号
        map.put("total_fee", totalFee)//总金额
        map.put("refund_fee", refundFee)//退款金额
        map.put("op_user_id", GlobalConstant.getString("mch_id"))//默认为商户号
        /**
         * 退款渠道，目前2中
         * ORIGINAL-原路退款，默认BALANCE-余额
         */
        map.put("refund_channel", refundChannel)//退款渠道
        map.put("service", "trade.single.refund");
        map.put("version", version);
        map.put("charset", charset);
        map.put("sign_type", sign_type);

        String key = GlobalConstant.getString("key");
        String reqUrl = GlobalConstant.getString("req_url");
        map.put("mch_id", GlobalConstant.getString("mch_id"));
        map.put("nonce_str", String.valueOf(new Date().getTime()));

        Map<String, String> params = SignUtils.paraFilter(map);
        StringBuilder buf = new StringBuilder((params.size() + 1) * 10);
        SignUtils.buildPayParams(buf, params, false);
        String preStr = buf.toString();
        String sign = MD5.sign(preStr, "&key=" + key, "utf-8");
        map.put("sign", sign);
        CloseableHttpResponse response = null;
        CloseableHttpClient client = null;
        String res = null;
        Map<String, String> resultMap = null;
        try {
            HttpPost httpPost = new HttpPost(reqUrl);
            StringEntity entityParams = new StringEntity(XmlUtils.parseXML(map), "utf-8");
            httpPost.setEntity(entityParams);
            httpPost.setHeader("Content-Type", "text/xml;charset=ISO-8859-1");
            client = HttpClients.createDefault();
            response = client.execute(httpPost);
            if (response != null && response.getEntity() != null) {
                resultMap = XmlUtils.toMap(EntityUtils.toByteArray(response.getEntity()), "utf-8");
                res = XmlUtils.toXml(resultMap)

                logger.info("================支付退款请求结果=================" + res);
                if (!SignUtils.checkParam(resultMap, key)) {
                    res = "验证签名不通过";
                }
            } else {
                res = "操作失败!";
            }
        } catch (Exception e) {
            res = "操作失败";
        } finally {
            if (response != null) {
                response.close();
            }
            if (client != null) {
                client.close();
            }
        }
        Map<String, String> result = new HashMap<String, String>();
        if (res.startsWith("<")) {
            result.put("status", "200");
            result.put("msg", "操作成功，请在日志文件中查看");
        } else {
            result.put("status", "500");
            result.put("msg", res);
        }
        ObjectMapper om = new ObjectMapper();
        om.setDateFormat(new SimpleDateFormat("yyyyMMddHH:mm:ss"));
        String json = om.writeValueAsString(resultMap)
        logger.info("===================退款接口返回结果=======================" + json)
        return json;
    }

}
